package design.pattern.Lu16ObserverPattern;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

/**
 * @program JavaBase
 * @description: 观察者模式 - jvm进程内，通用模版(实现jdk提供的能力)
 * @author: zhanglu
 * @create: 2022-05-19 17:02:00
 */
@Slf4j
public class ObserverPattern05 {

    static class Observable{
        public Map<String, List<Observer>> observerMap = new ConcurrentHashMap<>();
        public void addObserver(String topic, Observer observer){
            if(this.observerMap.containsKey(topic)){
                this.observerMap.get(topic).add(observer);
            }else {
                List<Observer> observerList = new CopyOnWriteArrayList<>();
                observerList.add(observer);
                this.observerMap.put(topic, observerList);
            }
        }
        public void notifyObservers(String topic, Object args){
            this.observerMap.get(topic).forEach(o -> o.handler(this, args));
        }
    }

    interface Observer<T>{
        void handler(Observable observable, T args);
    }

    static class ObserverHandler{
        private Observable observable;
        public ObserverHandler(){
            this.observable = new Observable();
        }
        protected void subscribe(String topic, Consumer<Object> consumer){
            Observer observer = (observable, args) -> {
                consumer.accept(args);
            };
            observable.addObserver(topic, observer);
        }
        protected Integer notify(String topic, Object args){
            observable.notifyObservers(topic, args);
            return 1;
        }
    }

    @Slf4j
    static class SystemController{
        public ObserverHandler observerHandler;

        public Object save(String data){
            log.info("新增一条记录");
            observerHandler.notify("save", data);
            return "ok";
        }

        public Object update(String data){
            log.info("更新一条记录");
            observerHandler.notify("save",data);
            return "ok";
        }

        public void init(){
            this.observerHandler = new ObserverHandler();
            //同一个事件，两个消费者订阅
            //消费者1逻辑
            this.observerHandler.subscribe("save", args -> {
                log.info("save订阅，参数：{}", args.toString());
            });
            //消费者2逻辑
            this.observerHandler.subscribe("save", args -> {
                log.info("update订阅，参数：{}", args.toString());
            });
        }

    }

    @Test
    public void test01(){
        SystemController controller = new SystemController();
        controller.init();
        Object test01 = controller.save("test01");
        System.out.println(test01.toString());
    }

}
